﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using System.Web.Routing;
using SuperWebSocket;
using System.Threading;
using WURFL.Aspnet.Extensions.Config;
using WURFL;
using SuperSocket.SocketBase;
using SuperSocket.SocketEngine;
using SuperSocket.SocketBase.Config;
using System.Configuration;
using SuperSocket.SocketEngine.Configuration;
using SuperSocket.Common;

namespace loveyou
{
    // Note: For instructions on enabling IIS6 or IIS7 classic mode, 
    // visit http://go.microsoft.com/?LinkId=9394801

    public class MvcApplication : System.Web.HttpApplication
    {
        private List<WebSocketSession> m_Sessions = new List<WebSocketSession>();
        private List<WebSocketSession> m_SecureSessions = new List<WebSocketSession>();
        private object m_SessionSyncRoot = new object();
        private object m_SecureSessionSyncRoot = new object();
        private Timer m_SecureSocketPushTimer;
        private int m_Index = 0;
        private bool webSocketSetted = false;

        #region WURFL

        public static void RegisterWurfl()
        {
            var configurer = new ApplicationConfigurer();
            var wurflManager = WURFLManagerBuilder.Build(configurer);
            HttpRuntime.Cache["WurflManagerKey"] = wurflManager;
        }

        public static IWURFLManager WurflManager
        {
            get { return HttpRuntime.Cache["WurflManagerKey"] as IWURFLManager; }
        }

        public static String WurflStartupTime;

        #endregion

        public static void RegisterGlobalFilters(GlobalFilterCollection filters)
        {
            filters.Add(new HandleErrorAttribute());
        }

        public static void RegisterRoutes(RouteCollection routes)
        {
            routes.IgnoreRoute("{resource}.axd/{*pathInfo}");

            routes.MapRoute(
                "Default", // Route name
                "{controller}/{action}/{id}", // URL with parameters
                new { controller = "Home", action = "Index", id = UrlParameter.Optional } // Parameter defaults
            );

        }

        protected void Application_Start()
        {
            AreaRegistration.RegisterAllAreas();

            RegisterGlobalFilters(GlobalFilters.Filters);
            RegisterRoutes(RouteTable.Routes);

            #region WURLF
            var startTime = DateTime.Now;
            RegisterWurfl();
            var endTime = DateTime.Now;
            WurflStartupTime = (endTime - startTime).TotalSeconds.ToString("##.##");
            #endregion
        }

        protected void Application_BeginRequest()
        {
            if (!webSocketSetted)
            {
                LogUtil.Setup();
                //StartSuperWebSocketByConfig();
                StartSuperWebSocketByProgramming();
                var ts = new TimeSpan(0, 0, 0, 0, 5000);
                m_SecureSocketPushTimer = new Timer(OnSecureSocketPushTimerCallback, new object(), ts, ts);

                webSocketSetted = true;
            }
        }

        void OnSecureSocketPushTimerCallback(object state)
        {
            lock (m_SecureSessionSyncRoot)
            {
                m_SecureSessions.ForEach(s => s.SendResponseAsync("Push data from WebSocket. [" + (m_Index++) + "] Current Time: " + DateTime.Now));
            }
        }

        void StartSuperWebSocketByConfig()
        {
            var serverConfig = ConfigurationManager.GetSection("socketServer") as SocketServiceConfig;

            if (!SocketServerManager.Initialize(serverConfig))
            {
                throw new Exception((serverConfig == null).ToString());
                return;
            }
            var socketServer = SocketServerManager.GetServerByName("SuperWebSocket") as WebSocketServer;
            var secureSocketServer = SocketServerManager.GetServerByName("SecureSuperWebSocket") as WebSocketServer;

            Application["WebSocketPort"] = socketServer.Config.Port;
            Application["SecureWebSocketPort"] = secureSocketServer.Config.Port;

            socketServer.NewMessageReceived += new SessionEventHandler<WebSocketSession, string>(socketServer_NewMessageReceived);
            socketServer.NewSessionConnected += new SessionEventHandler<WebSocketSession>(socketServer_NewSessionConnected);
            socketServer.SessionClosed += new SessionEventHandler<WebSocketSession, CloseReason>(socketServer_SessionClosed);

            secureSocketServer.NewSessionConnected += new SessionEventHandler<WebSocketSession>(secureSocketServer_NewSessionConnected);
            secureSocketServer.SessionClosed += new SessionEventHandler<WebSocketSession, CloseReason>(secureSocketServer_SessionClosed);

            if (!SocketServerManager.Start())
                SocketServerManager.Stop();
        }

        void socketServer_NewMessageReceived(WebSocketSession session, string e)
        {
            //判断操作标识符
            if (string.IsNullOrEmpty(e))
            {
                return;
            }

            //var data = e.Split('|');
            //var userName = data[0];
            //var actionCode = data[1];

            //var userInfo = GlobalConfig.OnlineUserList.ContainsKey(userName) ? GlobalConfig.OnlineUserList[userName] : null;
            //if (userInfo == null || !userInfo.IsController)
            //{
            //    return;
            //}

            //switch (actionCode)
            //{
            //    case "T"://Turn to page
            //        //记录为Ajax提供的同步信息
            //        Controllers.HomeController.currentPage = int.Parse(data[2]);
            //        SendToAll("T|" + data[2]);
            //        break;
            //    default:
            //        break;
            //}
            SendToAll(e);
        }

        void secureSocketServer_SessionClosed(WebSocketSession session, CloseReason reason)
        {
            lock (m_SecureSessionSyncRoot)
            {
                m_SecureSessions.Remove(session);
            }
        }

        void secureSocketServer_NewSessionConnected(WebSocketSession session)
        {
            lock (m_SecureSessionSyncRoot)
            {
                m_SecureSessions.Add(session);
            }
        }

        void StartSuperWebSocketByProgramming()
        {
            var socketServer = new WebSocketServer();
            socketServer.Setup(new RootConfig(),
                new ServerConfig
                {
                    Name = "SuperWebSocket",
                    Ip = "Any",
                    Port = 2011,
                    Mode = SocketMode.Async
                }, SocketServerFactory.Instance);

            socketServer.NewMessageReceived += new SessionEventHandler<WebSocketSession, string>(socketServer_NewMessageReceived);
            socketServer.NewSessionConnected += new SessionEventHandler<WebSocketSession>(socketServer_NewSessionConnected);
            socketServer.SessionClosed += new SessionEventHandler<WebSocketSession, CloseReason>(socketServer_SessionClosed);

            var secureSocketServer = new WebSocketServer();
            secureSocketServer.Setup(
                new RootConfig(),
                new ServerConfig
                {
                    Name = "SecureSuperWebSocket",
                    Ip = "Any",
                    Port = 2012,
                    Mode = SocketMode.Sync,
                    Security = "tls",
                    Certificate = new SuperSocket.SocketBase.Config.CertificateConfig
                    {
                        FilePath = Server.MapPath("~/localhost.pfx"),
                        Password = "supersocket",
                        IsEnabled = true
                    }
                }, SocketServerFactory.Instance);

            secureSocketServer.NewSessionConnected += new SessionEventHandler<WebSocketSession>(secureSocketServer_NewSessionConnected);
            secureSocketServer.SessionClosed += new SessionEventHandler<WebSocketSession, CloseReason>(secureSocketServer_SessionClosed);

            Application["WebSocketPort"] = socketServer.Config.Port;
            Application["SecureWebSocketPort"] = secureSocketServer.Config.Port;

            socketServer.Start();
            //secureSocketServer.Start();
        }

        void socketServer_NewSessionConnected(WebSocketSession session)
        {
            lock (m_SessionSyncRoot)
                m_Sessions.Add(session);

            SendToAll("connected");
        }

        void socketServer_SessionClosed(WebSocketSession session, CloseReason reason)
        {
            lock (m_SessionSyncRoot)
                m_Sessions.Remove(session);

            if (reason == CloseReason.ServerShutdown)
                return;

            SendToAll("disconnected");
        }

        void SendToAll(string message)
        {
            lock (m_SessionSyncRoot)
            {
                foreach (var s in m_Sessions)
                {
                    //s.SendResponse(message);
                    s.SendResponseAsync(message);
                }
            }
        }

        void Application_End(object sender, EventArgs e)
        {
            //  Code that runs on application shutdown
            m_SecureSocketPushTimer.Change(Timeout.Infinite, Timeout.Infinite);
            m_SecureSocketPushTimer.Dispose();
            SocketServerManager.Stop();
        }

    }
}